home *** CD-ROM | disk | FTP | other *** search
- ;/* CompareIO.c - Execute me to compile me with SAS/C 6.56
- sc DATA=FAR NMINC STRMERGE STREQ NOSTKCHK SAVEDS IGNORE=73 CompareIO.c
- slink FROM LIB:c.o,CompareIO.o TO CompareIO LIBRARY LIB:sc.lib,LIB:amiga.lib,lib:debug.lib
- quit ;*/
-
- /* (c) Copyright 1992-1999 Amiga, Inc. All rights reserved. */
- /* The information contained herein is subject to change without notice, */
- /* and is provided "as is" without warranty of any kind, either expressed */
- /* or implied. The entire risk as to the use of this information is */
- /* assumed by the user. */
-
- /* CompareIO.c uses packet level I/O to copy the standard input channel to the */
- /* standard output channel (as set up by the standard startup code, c.o). */
- /* CompareIO uses both synchronous and asynchronous I/O to perform the copy */
- /* and reports the time it takes to do each. */
-
-
- #include <exec/types.h>
- #include <dos/dosextens.h>
- #include <devices/timer.h>
-
- #include <clib/dos_protos.h>
- #include <clib/timer_protos.h>
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/alib_stdio_protos.h>
-
- #ifdef LATTICE
- int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
- void chkabort(void) { return; }
- #endif
-
-
- #define BUFSIZE 8192
-
- UBYTE *vers = "\0$VER: CompareIO 37.14 Nov-12-92";
-
- ULONG AsyncLoop(void);
- ULONG SyncLoop(void);
-
- extern struct Library *DOSBase;
- struct Library *TimerBase;
-
- struct MsgPort *myport;
-
- struct FileHandle *in, *out;
- BPTR results, in_start, out_start;
-
- struct DosPacket *sp_read, *sp_write;
-
- UBYTE buffer[BUFSIZE*2];
-
- struct timeval time_start, time_finish;
- struct timerequest timer_io;
-
- ULONG vfprintfargs[2]; /* An array of pointers */
-
-
- void main(void)
- {
- if (DOSBase->lib_Version >= 37)
- {
- if (results = Open("*", MODE_NEWFILE)) /* This is for printing the results. */
- { /* Since the example is already using the */
- /* standard I/O channels for its own */
- /* purposes, there needs to be a separate */
- /* channel to output the results. */
- if (!OpenDevice(TIMERNAME, UNIT_MICROHZ, &timer_io, 0L))
- {
- TimerBase = (struct Library *)timer_io.tr_node.io_Device;
-
- if (myport = CreateMsgPort())
- {
- in_start = Input(); /* Need to hold on to input and output so no one can */
- out_start = Output(); /* change them while this example is using them. */
- if (in = (struct FileHandle *)BADDR(in_start))
- {
- if (out = (struct FileHandle *)BADDR(out_start))
- {
- if (sp_read = AllocDosObject(DOS_STDPKT, NULL))
- {
- if (sp_write = AllocDosObject(DOS_STDPKT, NULL))
- {
- /* When AllocDosObject() allocates a StandardPacket, it takes */
- /* care of linking together the Message and DosPacket. */
- /* AllocDosObject() points the DosPacket's dp_Link field at */
- /* the StandardPacket's Message structure. It also points */
- /* the Message's mn_Node.ln_Name field at the DosPacket: */
- /* sp_read->dp_Link = sp_Msg; */
- /* sp_Msg->mn_Node.ln_Name = (STRPTR)sp_read; */
-
- sp_read->dp_Type = ACTION_READ; /* Fill out ACTION_READ packet. */
- sp_read->dp_Arg1 = in->fh_Arg1;
-
- sp_write->dp_Type = ACTION_WRITE; /* Fill out ACTION_WRITE packet. */
- sp_write->dp_Arg1 = out->fh_Arg1;
-
- VFPrintf(results, "\n Method Seconds Micros\n", NULL);
- VFPrintf(results, " ------------ ------- ------\n", NULL);
-
- GetSysTime(&time_start);
- if (AsyncLoop())
- {
- GetSysTime(&time_finish);
- SubTime(&time_finish, &time_start);
- vfprintfargs[0] = time_finish.tv_secs;
- vfprintfargs[1] = time_finish.tv_micro;
- VFPrintf(results,
- " Asynchronous: %3ld %7ld\n", &vfprintfargs[0]);
-
- GetSysTime(&time_start);
- if (SyncLoop())
- {
- GetSysTime(&time_finish);
- SubTime(&time_finish, &time_start);
- vfprintfargs[0] = time_finish.tv_secs;
- vfprintfargs[1] = time_finish.tv_micro;
- VFPrintf(results,
- " Synchronous: %3ld %7ld\n", &vfprintfargs[0]);
- }
- else
- VFPrintf(results, " ******* Stop ******\n", NULL);
- }
- else
- VFPrintf(results, " ******* Stop ******\n", NULL);
-
-
- FreeDosObject(DOS_STDPKT, sp_write);
- }
- FreeDosObject(DOS_STDPKT, sp_read);
- }
- }
- }
- DeleteMsgPort(myport);
- }
- CloseLibrary(TimerBase);
- }
- Close(results);
- }
- }
- }
-
- ULONG AsyncLoop()
- {
- struct StandardPacket *mysp;
- UBYTE *buf;
-
- LONG amount_read;
-
- BOOL sp_read_busy = TRUE, /* Is the ACTION_READ packet busy? */
- sp_write_busy = FALSE, /* Is the ACTION_WRITE packet busy? */
- done = FALSE; /* Is the program finished? */
- ULONG ok = TRUE;
-
-
- if (!((out->fh_Arg1) && (in->fh_Arg1))) /* Don't bother if in or out uses NIL: */
- return(FALSE);
- sp_read->dp_Arg2 = (LONG)buffer; /* The buffer to fill in. */
- sp_read->dp_Arg3 = BUFSIZE; /* The size of the Arg2 buffer. */
-
-
- SendPkt(sp_read, in->fh_Type, myport); /* Send initial read request. */
-
- sp_write->dp_Type = ACTION_WRITE; /* Fill out the ACTION_WRITE packet. */
- sp_write->dp_Arg1 = out->fh_Arg1;
- sp_write->dp_Arg2 = (LONG)&buffer[BUFSIZE]; /* Arg2 points to the buffer to write */
- sp_write->dp_Arg3 = 0L; /* out. At first glance, it might */
- sp_write->dp_Res1 = 0L; /* seem odd to bother setting Arg2 */
- /* when the program hasn't read anything yet. */
- /* This is to set up for the main loop. The */
- /* main loop swaps the ACTION_READ buffer with */
- /* the ACTION_WRITE buffer when it receives */
- /* a completed read. Likewise, dp_Arg3 and */
- /* dp_Res1 are set to make the ACTION_READ */
- /* look like it has a valid return value so */
- /* main loop won't fail the first time through */
- /* the loop. */
-
- /* main() has already taken care of sending the initial read to the */
- /* handler. Because we need the data from that read before we can */
- while (!done) /* do anything, the first thing to do is wait for its return. */
- {
- do /* Wait for the ACTION_READ to return. */
- {
- WaitPort(myport);
- while (mysp = (struct StandardPacket *)GetMsg(myport)) /* ...empty the port. */
- {
- /* If this message is the ACTION_READ packet, mark it as */
- /* no longer busy so we can use it to start another read. */
- if (mysp->sp_Pkt.dp_Type == ACTION_READ) sp_read_busy = FALSE;
-
- /* If this message is instead the ACTION_WRITE packet, */
- /* mark it as not busy. We need to check for this because */
- /* the WRITE_PACKET from the previous interation through */
- /* the loop might have come back before the ACTION_WRITE */
- /* from the previous interation. */
- else
- if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
- }
- } while (sp_read_busy); /* End of "wait for ACTION_READ" loop. */
-
- /* Get ready to send the next ACTION_READ. */
- buf = (UBYTE *)(sp_read->dp_Arg2); /* Hold on to the important stuff from the */
- amount_read = sp_read->dp_Res1; /* ACTION_READ we just got back so we can */
- /* reuse the packet to start a new read */
- /* while processing the last read's data. */
-
- while (sp_write_busy) /* Because this example only uses two buffers and */
- { /* the ACTION_WRITE might be using one of them, */
- /* this example has to wait for an outstanding */
- /* ACTION_WRITE to return before reusing the */
- /* ACTION_WRITE packet's buffer. */
- WaitPort(myport);
- while (mysp = (struct StandardPacket *)GetMsg(myport))
- if (mysp->sp_Pkt.dp_Type == ACTION_WRITE) sp_write_busy = FALSE;
- }
-
- if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
- {
- done = TRUE;
- ok = FALSE;
- }
- else
- {
- /* This tests the return values from the ACTION_READ and ACTION_WRITE */
- /* packets. The ACTION_READ packet returns the number of bytes it */
- /* read in dp_Res1, which was copied earlier into amount_read. If it */
- /* is 0, the read packet found the EOF. If it is negative, there was */
- /* an error. In the case of ACTION_WRITE, an error occurs if the */
- /* number of bytes that ACTION_WRITE was supposed to write (Arg3) */
- /* does not match the actual number it wrote, which ACTION_WRITE re- */
- /* turns in Res1. This test is the reason dp_Res1 and dp_Arg3 were */
- /* set to zero when the ACTION_WRITE packet was set up in main(). */
- if ((amount_read > 0) && (sp_write->dp_Res1 == sp_write->dp_Arg3))
- {
- sp_read->dp_Arg2 = sp_write->dp_Arg2; /* ACTION_WRITE is finished with its */
- /* buffer, use it in the next read. */
-
- SendPkt(sp_read, in->fh_Type, myport); /* Send the next ACTION_READ and mark */
- sp_read_busy = TRUE; /* the ACTION_READ as busy. */
-
- /* Process Buffer. This example doesn't do anything with the data from the */
- /* last ACTION_READ, it just passes it on to the STDOUT handler. */
-
-
- sp_write->dp_Arg2 = (LONG)buf; /* Set up the ACTION_WRITE packet. */
- sp_write->dp_Arg3 = amount_read;
- SendPkt(sp_write, out->fh_Type, myport); /* Send the next ACTION_WRITE and */
- sp_write_busy = TRUE; /* mark the ACTION_WRITE as busy. */
- }
- else /* A packet returned with a failure, so quit. */
- {
- done = TRUE;
- if ((amount_read < 0) || (sp_write->dp_Res1 != sp_write->dp_Arg3)) ok = FALSE;
- }
- }
- }
- return(ok);
- }
-
- ULONG SyncLoop()
- {
- BOOL done = FALSE;
- ULONG ok = TRUE;
- BPTR lock;
-
- if (!((out->fh_Arg1) && (in->fh_Arg1))) /* Don't bother if in or out uses NIL: */
- return(FALSE);
-
- sp_read->dp_Arg2 = (LONG)buffer;
- sp_read->dp_Arg3 = BUFSIZE*2;
- sp_write->dp_Arg2 = (LONG)buffer;
-
- if (lock = DupLockFromFH(in_start))
- {
- UnLock(lock); /* Make sure this is a filesystem and not */
- Seek(in_start, 0, OFFSET_BEGINNING); /* a console. If this is a filesystem, */
- } /* go to the beginning of the file. */
-
- while (!done)
- {
- if (SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
- {
- done = TRUE;
- ok = FALSE;
- }
- else
- {
- SendPkt(sp_read, in->fh_Type, myport);
- WaitPort(myport);
- while (GetMsg(myport));
-
- if (sp_read->dp_Res1 > 0)
- {
- sp_write->dp_Arg3 = sp_read->dp_Res1;
- SendPkt(sp_write, out->fh_Type, myport);
- WaitPort(myport);
- while (GetMsg(myport));
- if (sp_write->dp_Res1 != sp_write->dp_Arg3)
- {
- done = TRUE;
- ok = FALSE;
- }
- }
- else
- {
- done = TRUE;
- if (sp_read->dp_Res1 < 0) ok = FALSE;
- }
- }
- }
- return(ok);
- }
-
-